﻿using Microsoft.ServiceModel.Interop.Metro;
using Microsoft.ServiceModel.Interop.WebLogic;
using Microsoft.ServiceModel.Interop.WebSphere;
using Microsoft.ServiceModel.Interop.Wso2;
using RockBus.DataContracts;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace RockBus.Transport.Wcf
{
    public class BindingFactory
    {
        public BindingFactory()
        {
            var tempBindingTypeDict = new Dictionary<EndpointNameEnum, Type>();
            tempBindingTypeDict.Add(EndpointNameEnum.BasicHttpEndpoint, typeof(BasicHttpBinding));
            tempBindingTypeDict.Add(EndpointNameEnum.NetMsmqEndpoint, typeof(NetMsmqBinding));
            tempBindingTypeDict.Add(EndpointNameEnum.NetNamedPipeEndpoint, typeof(NetNamedPipeBinding));
            tempBindingTypeDict.Add(EndpointNameEnum.NetTcpEndpoint, typeof(NetTcpBinding));
            tempBindingTypeDict.Add(EndpointNameEnum.WsHttpEndpoint, typeof(WSHttpBinding));
            tempBindingTypeDict.Add(EndpointNameEnum.MetroEndpoint, typeof(MetroBinding));
            tempBindingTypeDict.Add(EndpointNameEnum.WebLogicEndpoint, typeof(WebLogicBinding));
            tempBindingTypeDict.Add(EndpointNameEnum.WebSphereEndpoint, typeof(WebSphereBinding));
            tempBindingTypeDict.Add(EndpointNameEnum.Wso2InteropEndpoint, typeof(Wso2InteropBinding));
            this.BindingTypeMap = tempBindingTypeDict;

            var tempSchemeMap = new Dictionary<EndpointNameEnum, string>();
            //tempSchemeMap.Add(EndpointNameEnum.BasicHttpEndpoint, "https");
            tempSchemeMap.Add(EndpointNameEnum.BasicHttpEndpoint, "http");
            tempSchemeMap.Add(EndpointNameEnum.NetMsmqEndpoint, "net.msmq");
            tempSchemeMap.Add(EndpointNameEnum.NetNamedPipeEndpoint, "net.pipe");
            tempSchemeMap.Add(EndpointNameEnum.NetTcpEndpoint, "net.tcp");
            tempSchemeMap.Add(EndpointNameEnum.WsHttpEndpoint, "http");
            tempSchemeMap.Add(EndpointNameEnum.MetroEndpoint, "http");
            tempSchemeMap.Add(EndpointNameEnum.WebLogicEndpoint, "http");
            tempSchemeMap.Add(EndpointNameEnum.WebSphereEndpoint, "http");
            tempSchemeMap.Add(EndpointNameEnum.Wso2InteropEndpoint, "https");
            tempSchemeMap.Add(EndpointNameEnum.Ws2007FederationHttpEndpoint, "http");
            this.SchemeMap = tempSchemeMap;
        }

        public Binding CreateBinding(EndpointNameEnum endpointName, SecurityMode defaultSecurityMode = SecurityMode.None)
        {
            Binding binding = null;
            switch (endpointName)
            {
                case EndpointNameEnum.NetMsmqEndpoint:
                    binding = new NetMsmqBinding((NetMsmqSecurityMode)defaultSecurityMode);
                    break;

                case EndpointNameEnum.NetNamedPipeEndpoint:
                    binding = new NetNamedPipeBinding((NetNamedPipeSecurityMode)defaultSecurityMode);
                    break;

                case EndpointNameEnum.NetTcpEndpoint:
                    binding = new NetTcpBinding(defaultSecurityMode);
                    break;

                case EndpointNameEnum.BasicHttpEndpoint:
                    binding = new BasicHttpBinding((BasicHttpSecurityMode)defaultSecurityMode);
                    break;

                case EndpointNameEnum.WsHttpEndpoint:
                    binding = new WSHttpBinding(defaultSecurityMode);
                    break;

                case EndpointNameEnum.Custom:
                    throw new ConfigurationErrorsException("Cannot create default Binding for Custom endpoints.");
                case EndpointNameEnum.WebSphereEndpoint:
                    binding = new WebSphereBinding((WebSphereSecurityMode)defaultSecurityMode);
                    break;

                case EndpointNameEnum.WebLogicEndpoint:
                    binding = new WebLogicBinding((WebLogicSecurityMode)defaultSecurityMode);
                    break;

                case EndpointNameEnum.MetroEndpoint:
                    binding = new MetroBinding((MetroSecurityMode)defaultSecurityMode);
                    break;

                case EndpointNameEnum.Wso2InteropEndpoint:
                    binding = new Wso2InteropBinding();
                    break;

                case EndpointNameEnum.Ws2007FederationHttpEndpoint:
                    binding = new WS2007FederationHttpBinding();
                    break;

                default:
                    break;
            }
            return binding;
        }

        public IReadOnlyDictionary<EndpointNameEnum, Type> BindingTypeMap { get; private set; }

        public IReadOnlyDictionary<EndpointNameEnum, string> SchemeMap { get; private set; }
    }
}